<?php
/**
 * Note:     [Description]
 * Author:   longhui.huang <1592328848@qq.com>
 * DateTime: 2024/1/30 14:20
 */
declare(strict_types=1);

namespace App\Utility\Rsa;

/**
 * Author:   XueSi <1592328848@qq.com>
 * Description: Rsa 工具类，公钥私钥生成，加解密
 * DateTime: 2024/1/30 14:34
 * Class RsaUtils
 *
 * @package     App\Utility\Rsa
 */
class RsaUtils
{
    private const SRC = "123456";

    /**
     * 公钥解密
     * @param string $publicKeyText
     * @param string $text
     * @return string
     */
    public static function decryptByPublicKey(string $publicKeyText, string $text)
    {
        $key = "-----BEGIN PUBLIC KEY-----\n" . wordwrap($publicKeyText, 64, "\n", true) . "\n-----END PUBLIC KEY-----";
        openssl_public_decrypt(base64_decode($text), $result, $key);
        return $result;
    }

    /**
     * 私钥加密
     * @param string $privateKeyText
     * @param string $text
     * @return string
     */
    public static function encryptByPrivateKey(string $privateKeyText, string $text)
    {
        $privateKey = "-----BEGIN RSA PRIVATE KEY-----\n" . wordwrap($privateKeyText, 64, "\n", true) . "\n-----END RSA PRIVATE KEY-----";
        openssl_private_encrypt($text, $result, $privateKey);
        return base64_encode($result);
    }

    /**
     * 私钥解密
     * @param string $privateKeyText
     * @param string $text
     * @return string
     */
    public static function decryptByPrivateKey(string $privateKeyText, string $text)
    {
        $key = "-----BEGIN RSA PRIVATE KEY-----\n" . wordwrap($privateKeyText, 64, "\n", true) . "\n-----END RSA PRIVATE KEY-----";
        openssl_private_decrypt(base64_decode($text), $result, $key);
        return $result;
    }

    /**
     * 公钥加密
     * @param string $publicKeyText
     * @param string $text
     * @return string
     */
    public static function encryptByPublicKey(string $publicKeyText, string $text)
    {
        $publicKey = "-----BEGIN PUBLIC KEY-----\n" . wordwrap($publicKeyText, 64, "\n", true) . "\n-----END PUBLIC KEY-----";
        openssl_public_encrypt($text, $result, $publicKey);
        return base64_encode($result);
    }

    public static function generateKeyPair()
    {
        $config = [
            "private_key_bits" => 1024,
            "private_key_type" => OPENSSL_KEYTYPE_RSA,
        ];
        $res = openssl_pkey_new($config);
        openssl_pkey_export($res, $privateKey);
        $privateKey = str_replace(['-----BEGIN PRIVATE KEY-----', '-----END PRIVATE KEY-----', "\n"], [''], $privateKey);
        $publicKey = openssl_pkey_get_details($res)['key'];
        $publicKey = str_replace(['-----BEGIN PUBLIC KEY-----', '-----END PUBLIC KEY-----', "\n"], [''], $publicKey);
        return new RsaKeyPair($publicKey, $privateKey);
    }

    /**
     * 公钥加密私钥解密
     */
    private static function test1($keyPair)
    {
        echo "***************** 公钥加密私钥解密开始 *****************\n";
        $text1 = self::encryptByPublicKey($keyPair->getPublicKey(), self::SRC);
        $text2 = self::decryptByPrivateKey($keyPair->getPrivateKey(), $text1);
        echo "加密前：" . self::SRC . "\n";
        echo "加密后：" . $text1 . "\n";
        echo "解密后：" . $text2 . "\n";
        if (self::SRC === $text2) {
            echo "解密字符串和原始字符串一致，解密成功\n";
        } else {
            echo "解密字符串和原始字符串不一致，解密失败\n";
        }
        echo "***************** 公钥加密私钥解密结束 *****************\n";
    }

    /**
     * 私钥加密公钥解密
     */
    private static function test2($keyPair)
    {
        echo "***************** 私钥加密公钥解密开始 *****************\n";
        $text1 = self::encryptByPrivateKey($keyPair->getPrivateKey(), self::SRC);
        $text2 = self::decryptByPublicKey($keyPair->getPublicKey(), $text1);
        echo "加密前：" . self::SRC . "\n";
        echo "加密后：" . $text1 . "\n";
        echo "解密后：" . $text2 . "\n";
        if (self::SRC === $text2) {
            echo "解密字符串和原始字符串一致，解密成功\n";
        } else {
            echo "解密字符串和原始字符串不一致，解密失败\n";
        }
        echo "***************** 私钥加密公钥解密结束 *****************\n";
    }

    public static function main()
    {
        echo "\n";
        $keyPair = self::generateKeyPair();
        echo "公钥：" . $keyPair->getPublicKey() . "\n";
        echo "私钥：" . $keyPair->getPrivateKey() . "\n";
        echo "\n";
        self::test1($keyPair);
        echo "\n";
        self::test2($keyPair);
        echo "\n";
    }
}
//RsaUtils::main();
